package multicastqosrouting;

import com.mxgraph.layout.mxFastOrganicLayout;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxConstants;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxStylesheet;
import java.awt.Color;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.StringTokenizer;
import javax.swing.JApplet;
import org.jgraph.JGraph;
import org.jgrapht.ListenableGraph;
import org.jgrapht.ext.JGraphModelAdapter;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.ListenableDirectedGraph;

/**
 *
 * @author yeison
 */
public class Graph extends JApplet {
    /*
     * Constructor
     */
    
    public Graph() {
        init();
    }
    
    public Graph(String pathToFile) {
        i_pathToFile = pathToFile;
        init();
        generateViewGraph();
        
    }

    /*
     * Getters
     */
    public ListenableGraph getGraph() {
        return g;
    }
    
    public mxGraphComponent getGraphView() {
        return graphView;
    }

    /*
     * Method: init
     */
    /*
     * Default applet constructor, initialize the graph
     */
    public void init() {

        // create a visualization using JGraph, via an adapter
        m_jgAdapter = new JGraphModelAdapter(g);
        
        
        JGraph jgraph = new JGraph(m_jgAdapter);
        adjustDisplaySettings(jgraph);
        getContentPane().add(jgraph);
        setSize(500, 400);
        generateGraphFromFile();
        
    }

    /*
     * Method : generateGraphFromFile()
     */
    /*
     * Generates the JGraphT graph based on the topology matrix passed to the
     * constructor of the class.
     */
    private void generateGraphFromFile() {
        int i = 0;
        int j = 0;
        try {
            FileInputStream fstream = new FileInputStream(i_pathToFile);
            FileInputStream fstream2 = new FileInputStream(i_pathToFile);
            DataInputStream in = new DataInputStream(fstream);
            DataInputStream in2 = new DataInputStream(fstream2);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            BufferedReader br2 = new BufferedReader(new InputStreamReader(in2));
            String strLine;
            String line = br2.readLine();
            StringTokenizer nodeCount = new StringTokenizer(line, " ");
            adjacencyMatrix = new int[nodeCount.countTokens()][nodeCount.countTokens()];
            while ((strLine = br.readLine()) != null) {
                // Print the content on the console
                //System.out.println(strLine);
                StringTokenizer nodeId = new StringTokenizer(strLine, " ");
                //System.out.println(nodeId.countTokens());
                int nodes = nodeId.countTokens();
                
                while (nodeId.hasMoreTokens()) {
                    String digits = nodeId.nextToken();
                    adjacencyMatrix[i][j] = Integer.parseInt(digits.trim());
                    j++;
                    //System.out.println(Integer.parseInt(digits.trim()));
                    //System.out.println("M: " + adjacencyMatrix[i][j]);                    
                }
                i++;
                j = 0;
            }
            in.close();
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
        vertices = new Object[adjacencyMatrix.length];
        
//        System.out.println("Topology Matrix: ");
//        for (int k = 0; k < adjacencyMatrix.length; k++) {
//            for (int l = 0; l < adjacencyMatrix[k].length; l++) {
//                System.out.print(adjacencyMatrix[k][l] + " ");
//            }
//            System.out.println();
//        }
        
        for (int k = 0; k < adjacencyMatrix.length; k++) {
            g.addVertex((long) k);
        }
        for (int k = 0; k < adjacencyMatrix.length; k++) {
            for (int l = 0; l < adjacencyMatrix[k].length; l++) {
                if (adjacencyMatrix[k][l] == 1) {
                    g.addEdge((long) k, (long) l);
                }
            }
            
        }
        
    }

    /*
     * Method : generateViewGraph()
     */
    /*
     * Generates the JGraphX (mxGraph) graph based on the topology matrix passed
     * to the constructor of the class.
     */    
    private void generateViewGraph() {
        graph = new mxGraph();

        // Create a new style (circle)
        mxStylesheet styleSheet = graph.getStylesheet();
        Hashtable<String, Object> style = new Hashtable<String, Object>();
        style.put(mxConstants.STYLE_SHAPE, mxConstants.SHAPE_ELLIPSE);
        style.put(mxConstants.STYLE_OPACITY, 50);
        style.put(mxConstants.STYLE_FONTCOLOR, "black");
        style.put(mxConstants.STYLE_FILLCOLOR, "none");
        style.put(mxConstants.STYLE_STROKECOLOR, "black");
        styleSheet.putCellStyle("ROUNDED", style);
        
        Object parent = graph.getDefaultParent();
        
        
        graph.getModel().beginUpdate();
        try {
            
            for (int k = 0; k < adjacencyMatrix.length; k++) {
                vertices[k] =
                        graph.insertVertex(parent, null, k, POSITION, POSITION,
                        DIAMETER, DIAMETER, "ROUNDED");
                
            }
            
            for (int k = 0; k < adjacencyMatrix.length; k++) {
                for (int l = 0; l < adjacencyMatrix[k].length; l++) {
                    if (adjacencyMatrix[k][l] == 1) {
                        graph.insertEdge(parent, null, k + "-" + l, vertices[k],
                                vertices[l], "DefaultEdge;strokeColor=black;fontColor=black");
                    }
                }
                
            }
            
        } finally {
            graph.getModel().endUpdate();
        }
        graphView = new mxGraphComponent(graph);
        mxFastOrganicLayout layout = new mxFastOrganicLayout(graph);
        // mxCircleLayout layout = new mxCircleLayout(graph);
        layout.execute(graph.getDefaultParent());
        
    }

    /*
     * Method : adjustDisplaySettings
     */
    /*
     * Adjust the display setting when visualizing with JGraphT.
     */    
    private void adjustDisplaySettings(JGraph jg) {
        jg.setPreferredSize(DEFAULT_SIZE);
        
        Color c = DEFAULT_BG_COLOR;
        String colorStr = null;
        
        try {
            colorStr = getParameter("bgcolor");
        } catch (Exception e) {
        }
        
        if (colorStr != null) {
            c = Color.decode(colorStr);
        }
        
        jg.setBackground(c);
    }
    //instance Variables
    private JGraphModelAdapter m_jgAdapter;
    private ListenableGraph g = new ListenableDirectedGraph(DefaultEdge.class);
    private String i_pathToFile;
    private int[][] adjacencyMatrix;
    private Object[] vertices;
    private mxGraph graph;
    private mxGraphComponent graphView;
    //Constants
    private static final Color DEFAULT_BG_COLOR = Color.WHITE;
    private static final Dimension DEFAULT_SIZE = new Dimension(530, 320);
    private static final int POSITION = 0;
    private static final int DIAMETER = 30;
}
